/*
 * @(#)AdapterSecurity.java      2018/8/16
 *
 * 百得利集团拥有完全的版权
 * 使用者必须经过许可
 */
package com.deepexi.adapter.common.security;


import com.deepexi.adapter.common.DateUtils;

import java.util.Base64;
import java.util.Date;

/**
 * 功能：安全
 *
 * @author twfx7
 * @since JDK 1.8
 */
public class AdapterSecurity {

	/**
	 * SAP加密
	 *
	 *  2345620180803173901467
	 * 23456  20180803173901  467
	 * 签名明文：系统标识（23456）+日期（20180803）+时间（173901）+校验码（467）
	 * 校验码生成规则：
	 * 		系统标识第4位*KEY01+系统标识第5位*KEY02+日期第8位* KEY03+时*KEY04+分*KEY05+秒*KEY06
	 * 		例: 5*KEY01+6*KEY02+3*KEY03+17*KEY04+39*KEY05+01*KEY06 = 467
	 *
	 * 		运维会动态变更，临时写死:
				 系统标识	56142
				 KEY01	　5
				 KEY02	　7
				 KEY03	　2
				 KEY04	　9
				 KEY05	　1
				 KEY06	　3

			 校验码截取上面计算值的最后3位，如果位数不到3位，在前面补零
			 使用BASE64对校验码明文进行加密和解密
	 * @author yuzhisheng
	 * @since JDK 1.8
	 */
	public static class Sap {
		private static int[] sys = new int[]{5,6,1,4,2};
		private static int[] keys = new int[]{5,7,2,9,1,3};

		/** 获取签名明文: Secretkey  (五分钟内有效) */
		public static String getSecretkey() {
			Date d = new Date(System.currentTimeMillis() - 1000);
			String date = DateUtils.getDate(d, null);
			String secretkey = String.valueOf(sys[3] * keys[0] + sys[4] * keys[1] + Integer.valueOf(date.substring(7,8)) * keys[2] + Integer.valueOf(DateUtils.getDate(d, "HH")) * keys[3] + Integer.valueOf(DateUtils.getDate(d, "mm")) * keys[4] + Integer.valueOf(DateUtils.getDate(d, "ss")) * keys[5]);
			secretkey = secretkey.length() >2 ? secretkey.substring(secretkey.length()-3, secretkey.length()) : secretkey.length() >1 ? "0"+secretkey : "00"+secretkey;
			return AdapterSecurity.base64(new StringBuffer().append(sys[0]).append(sys[1]).append(sys[2]).append(sys[3]).append(sys[4]).append(date).append(secretkey).toString());
		}

		public static void main(String[] ar) {
			String aa = getSecretkey();
            System.out.println(aa);
            System.out.println(unBase64(aa));
//			System.out.println("1234".substring(2,3));
//			System.out.println("1234".charAt(2));
		}
	}

	/**  base64编码(utf-8) */
	public static String base64(String str) {
		try {
			return Base64.getEncoder().encodeToString( str.getBytes("utf-8"));
		}catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**  base64解码(utf-8) */
	public static String unBase64(String asB64) {
		return new String(Base64.getDecoder().decode(asB64));
	}

	/**
	 *  mobyAdapter(本项目)
	 *
	 *  secretkey 五分钟内有效
	 *
	 * @author yuzhisheng
	 * @since JDK 1.8
	 */
	public static class MobyAdapter {

		private static int[] sys = Sap.sys;
		private static int[] keys = Sap.keys;

		private static String sysStr = merge(sys);

		/** 校验签名明文: secretkey
		 *  @param secretkey 公文
		 *  @return null为成功，有值表示失败信息
		 */
		public static String checkSecretkey(String secretkey) {
			secretkey = AdapterSecurity.unBase64(secretkey);
			if( ! sysStr.substring(0,5).equals(secretkey.substring(0,5))) return "系统标识错误";
			String date = secretkey.substring(5, 19);
			long ct = System.currentTimeMillis();
			long dateLong = DateUtils.stringToDate(date, null).getTime();
			if(ct - 300000 > dateLong) return "超时"; // 300000毫秒 = 5分钟
			if(ct + 1000 < dateLong) return "来自未来的请求";
			Date d = DateUtils.stringToDate(date, null);
			String checkSecretkey = String.valueOf(sys[3] * keys[0] + sys[4] * keys[1] + Integer.valueOf(date.substring(7,8)) * keys[2] + Integer.valueOf(DateUtils.getDate(d, "HH")) * keys[3] + Integer.valueOf(DateUtils.getDate(d, "mm")) * keys[4] + Integer.valueOf(DateUtils.getDate(d, "ss")) * keys[5]);
			checkSecretkey = checkSecretkey.length() >2 ? checkSecretkey.substring(checkSecretkey.length()-3, checkSecretkey.length()) : checkSecretkey.length() >1 ? "0"+checkSecretkey : "00"+checkSecretkey;
			if( ! checkSecretkey.equals(secretkey.substring(19))) return "密钥计算错误";
			return null;
		}

		private static String merge(int[] arr) {
			if(arr == null) return null;
			StringBuffer s = new StringBuffer();
			for(int i : arr) s.append(i);
			return s.toString();
		}

		public static void main(String[] ar) {
			String s = Sap.getSecretkey();
			String res = MobyAdapter.checkSecretkey(s);
			System.out.println(s);
			System.out.println(res);
			System.out.println(DateUtils.getDate(new Date(System.currentTimeMillis() - 1000000), null));
		}
	}
}
